package org.v2ray.rocket.proxy.support.user

import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.launch
import org.v2ray.rocket.proxy.support.R
import org.v2ray.rocket.proxy.support.base.BaseViewModel
import org.v2ray.rocket.proxy.support.network.RequestUrl
import org.v2ray.rocket.proxy.support.network.model.BaseResponse
import org.v2ray.rocket.proxy.support.network.model.UserInfoModel
import org.v2ray.rocket.proxy.support.network.msg
import org.v2ray.rocket.proxy.support.utils.MD5Utils.calculateMD5
import org.v2ray.rocket.proxy.support.utils.ResourceUtil
import rxhttp.toFlow
import rxhttp.wrapper.param.RxHttp
import rxhttp.wrapper.param.toFlowResponse
import www.sanju.motiontoast.MotionToastStyle

class UserViewModel(
) : BaseViewModel<UserIntent, UserState, UserEffect>() {

    override fun createInitialState(): UserState {
        return UserState()
    }

    override fun handleIntent(intent: UserIntent) {
        when (intent) {
            is UserIntent.SendVerifyCode -> {
                sendVerifyCode(intent.phoneNumber)
            }

            is UserIntent.LoginByPassword -> {
                loginByPassword(intent.phoneNumber, intent.password)
            }

            is UserIntent.LoginBySmsCode -> {
                loginBySmsCode(intent.phoneNumber, intent.smsCode)
            }

            is UserIntent.Register -> {
                register(
                    intent.phoneNumber,
                    intent.smsCode,
                    intent.password,
                    intent.imei,
                    intent.androidID,
                    intent.mac
                )
            }

            is UserIntent.ResetPassword -> {
                resetPassword(intent.phoneNumber, intent.smsCode, intent.password)
            }

            is UserIntent.SwitchLoginType -> {
                switchLoginType()
            }
        }
    }

    override fun UserState.updateLoadingState(isLoading: Boolean): UserState {
        return copy(isLoading = isLoading)
    }

    /**
     * 发送验证码
     */
    private fun sendVerifyCode(phoneNumber: String) {
        RxHttp.get(RequestUrl.SEND_VERIFY_CODE)
            .add("tel", phoneNumber)
            .toFlow<BaseResponse<Any>>()
            .onStart {
                showLoading()
            }
            .onEach {
                hideLoading()
                if (it.isSuccess()) {
                    showToast(
                        ResourceUtil.resourceString(R.string.send_verification_code_success),
                        MotionToastStyle.SUCCESS
                    )
                } else {
                    showToast(it.msg.toString(), MotionToastStyle.ERROR)

                }
            }
            .catch { e ->
                hideLoading()
                showToast(e.msg, MotionToastStyle.ERROR)
            }
            .flowOn(Dispatchers.IO)
            .launchIn(viewModelScope)
    }

    /**
     * 密码登录
     */
    private fun loginByPassword(phoneNumber: String, password: String) {
        RxHttp.postJson(RequestUrl.LOGIN_BY_PASSWORD)
            .add("tel", phoneNumber)
            .add("code", calculateMD5(password))
            .toFlowResponse<UserInfoModel>()
            .onStart {
                showLoading()
            }
            .onEach {
                hideLoading()
                setState {
                    copy(
                        userInfo = userInfo,
                        isLoggedIn = true
                    )
                }
                setEffect { UserEffect.LoginSuccess(it) }
                showToast(
                    ResourceUtil.resourceString(R.string.login_success),
                    MotionToastStyle.SUCCESS
                )
            }
            .catch { e ->
                hideLoading()
                showToast(e.msg, MotionToastStyle.ERROR)
            }
            .flowOn(Dispatchers.IO)
            .launchIn(viewModelScope)
    }

    /**
     * 验证码登录
     */
    private fun loginBySmsCode(phoneNumber: String, smsCode: String) {
        RxHttp.postJson(RequestUrl.LOGIN_BY_SMS)
            .add("tel", phoneNumber)
            .add("code", smsCode)
            .toFlowResponse<UserInfoModel>()
            .onStart {
                showLoading()
            }
            .onEach {
                hideLoading()
                setState {
                    copy(
                        userInfo = userInfo,
                        isLoggedIn = true
                    )
                }
                setEffect { UserEffect.LoginSuccess(it) }
                showToast(
                    ResourceUtil.resourceString(R.string.login_success),
                    MotionToastStyle.SUCCESS
                )
            }
            .catch { e ->
                hideLoading()
                showToast(e.msg, MotionToastStyle.ERROR)
            }
            .flowOn(Dispatchers.IO)
            .launchIn(viewModelScope)
    }

    /**
     * 注册
     */
    private fun register(
        phoneNumber: String,
        smsCode: String,
        password: String,
        imei: String?,
        androidID: String?,
        mac: String?
    ) {

        RxHttp.postJson(RequestUrl.REGISTER)
            .add("tel", phoneNumber)
            .add("code", smsCode)
            .add("passwd", calculateMD5(password))
            .addHeader("androidID", androidID ?: "")
            .addHeader("mac", mac ?: "")
            .addHeader("imei", imei ?: "")
            .toFlow<Any>()
            .onStart {
                showLoading()
            }
            .onEach {
                // 注册成功后自动登录
                loginByPassword(phoneNumber, password)
            }
            .catch { e ->
                hideLoading()
                showToast(e.msg, MotionToastStyle.ERROR)
            }
            .flowOn(Dispatchers.IO)
            .launchIn(viewModelScope)
    }

    /**
     * 重置密码
     */
    private fun resetPassword(phoneNumber: String, smsCode: String, password: String) {
        RxHttp.postJson(RequestUrl.RESET_PASSWORD)
            .add("tel", phoneNumber)
            .add("code", smsCode)
            .add("passwd", calculateMD5(password))
            .toFlowResponse<Any>()
            .onStart {
                showLoading()
            }
            .onEach {
                hideLoading()
                setEffect { UserEffect.ResetPasswordSuccess }
                showToast(
                    ResourceUtil.resourceString(R.string.reset_password_success),
                    MotionToastStyle.SUCCESS
                )
            }
            .catch { e ->
                hideLoading()
                showToast(e.msg, MotionToastStyle.ERROR)
            }
            .flowOn(Dispatchers.IO)
            .launchIn(viewModelScope)
    }

    /**
     * 切换登录方式
     */
    private fun switchLoginType() {
        setState { copy(isLoginByPassword = !isLoginByPassword) }
    }
}